package gao.xiaolei.service;

import java.io.*;
import java.util.Optional;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import gao.xiaolei.entity.Image;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import gao.xiaolei.dao.InterfaceImageDao;
import gao.xiaolei.util.Md5;

@Service("ImageService")
@RefreshScope
public class ImageService implements InitializingBean {

    @Value("${fileConfig.defaultPath}" + "/")
    private String savePath;

    @Resource(name = "ImageDao")
    private InterfaceImageDao imageDao;

    @Transactional
    public String uploadImage(MultipartFile file,@Nullable String defineHashCode) throws IOException {
        // 获取文件的二进制数组
        byte[] fileByte = file.getBytes();
        //获取文件后缀
        String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
        //获取文件长度
        Long fileLength = file.getSize();
        // 将图片本身转化为32位哈希码,用于文件名来储存,防止文件重复,如果自己提供了哈希码就根据此哈希码作为文件名
        String fileHash = defineHashCode==null?Md5.md5HashCode32(fileByte):defineHashCode;
        // 在哈希码的前两位和后面其余位之间加/,从而实现储存的时候自己生成对应的文件夹来储存
        String twoFront = fileHash.substring(0, 2);
        String fileHashPath = makePath(fileHash);
        // 判断文件夹下有没有文件哈希值前两位对应的目录,如果没有则创建
        File filePath = new File(savePath + twoFront);
        // 这里判断数据库里面是否有相同哈希值的图片,如果有则直接数据库的引用值加1
        Optional<Image> optImg = imageDao.findById(fileHash);
        if (optImg.isPresent())
			imageDao.updateLeadCount(optImg.get().getLeadConut() + 1,fileHash);
        else {
            if (!filePath.exists())// 如果文件夹不存在
                filePath.mkdir();// 创建文件夹
            // 将路径和文件名进行组合构建File对象
            File fileToSave = new File(savePath + fileHashPath);
            // 通过Spring的文件复制函数将二进制格式的文件复制到对应的路径下
            FileCopyUtils.copy(fileByte, fileToSave);
        }
        //将新建的文件信息同步至数据库
        Image i = new Image();
        i.setHashCode(fileHash);
        i.setFilePath(fileHashPath);
        i.setFileType(fileType);
        i.setLeadConut(1);
        i.setDownloadConut(0);
        i.setLength(fileLength);
        imageDao.save(i);
        // 返回文件储存路径
        return fileHash;
    }

    @Transactional
    //用于删除图片(仅仅是将引用数-1)
    public String deleteImage(String hashCode) {
        int leadCount = imageDao.getLeadCount(hashCode);
        if (leadCount > 0)
            imageDao.updateLeadCount(leadCount -1, hashCode);
        return hashCode;
    }


    @Transactional
    //获取图片
    public byte[] getImage(String hashCode) throws IOException {
		System.out.println(imageDao.getLeadCount(hashCode));
        if (imageDao.getLeadCount(hashCode) < 1)//如果引用数<1,说明该图片理论上被删除了，应该不给获取
            return null;
        String newFileHash = makePath(hashCode);
        File filePath = new File(savePath + newFileHash);
        InputStream fis = null;
        try {
            fis = new FileInputStream(filePath);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        byte[] imageContent = FileCopyUtils.copyToByteArray(fis);
		imageDao.updateDownloadCount(imageDao.getDownLoadCount(hashCode)+1,hashCode);//将文件下载次数加1
        return imageContent;
    }

    private String makePath(String hashCode) {
        return hashCode.substring(0, 2) + "/" + hashCode.substring(2, 32);
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        File filePath = new File(savePath);
        if (!filePath.exists())// 如果文件夹不存在
            filePath.mkdir();// 创建文件夹
    }
}
